﻿using System;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Text;
using System.Globalization;
using System.ComponentModel;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

using HsjCommon = PickGold.Common;

namespace PickGold.Security
{
	/// <summary>
	/// Security
	/// </summary>
	public static class Common
	{
		private static X509Certificate2 Certificate;

		/// <summary>
		/// X509 Certificate
		/// </summary>
		public static X509Certificate2 X509
		{
			set
			{
				Certificate = value;
			}
			get
			{
				if (Certificate == null)
				{
					var t = typeof(Reflector);
					using (var rs = t.Assembly.GetManifestResourceStream(t.Namespace + "." + HsjCommon.HSJ + ".pfx"))
					{
						var bs = new byte[rs.Length];
						rs.Read(bs, 0, bs.Length);
						Certificate = new X509Certificate2(bs, HsjCommon.HSJ);
					}
				}
				return Certificate;
			}
		}

		private static byte[] FillKey(byte[] data, int size)
		{
			size /= 8;
			if (data.Length == size)
				return data;

			var bs = new byte[size];
			var dl = data.Length;
			if (dl > size)
			{
				Array.Copy(data, 0, bs, 0, size);
				return bs;
			}

			for (var i = 0; i < size; i += dl)
				Array.Copy(data, 0, bs, i, size - i - dl > 0 ? dl : size - i);
			return bs;
		}

		/// <summary>
		/// AES 对称加密
		/// </summary>
		/// <param name="input">input</param>
		/// <param name="key">key</param>
		/// <param name="iv">iv</param>
		/// <returns>return</returns>
		[Description("AES 对称加密")]
		public static byte[] AesEncode([Description("要加密的数据")]byte[] input, [Description("加密密钥")]byte[] key, [Description("加密向量")]byte[] iv)
		{
			if (input == null || input.Length == 0)
				return null;

			if ((key == null || key.Length == 0) &&
				(iv == null || iv.Length == 0))
				return null;

			var aes = RijndaelManaged.Create();
			if (key == null || key.Length == 0)
			{
				key = iv;
				if (iv.Length >= aes.KeySize + aes.KeySize / 2)
				{
					var vs = new byte[aes.KeySize];
					Array.Copy(iv, 0, vs, 0, vs.Length);
					aes.Key = vs;
					vs = new byte[aes.KeySize / 2];
					Array.Copy(iv, aes.KeySize, vs, 0, vs.Length);
					aes.IV = vs;
				}
				else
				{
					aes.Key = FillKey(key, aes.KeySize);
					aes.IV = FillKey(iv, aes.KeySize / 2);
				}
			}
			else if (iv == null || iv.Length == 0)
			{
				iv = key;
				if (key.Length >= aes.KeySize + aes.KeySize / 2)
				{
					var vs = new byte[aes.KeySize];
					Array.Copy(key, 0, vs, 0, vs.Length);
					aes.Key = vs;
					vs = new byte[aes.KeySize / 2];
					Array.Copy(key, aes.KeySize, vs, 0, vs.Length);
					aes.IV = vs;
				}
				else
				{
					aes.Key = FillKey(key, aes.KeySize);
					aes.IV = FillKey(iv, aes.KeySize / 2);
				}
			}
			else
			{
				aes.Key = FillKey(key, aes.KeySize);
				aes.IV = FillKey(iv, aes.KeySize / 2);
			}
			using (var ms = new MemoryStream())
			{
				using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
				{
					cs.Write(input, 0, input.Length);
					cs.FlushFinalBlock();
					cs.Close();
					input = ms.ToArray();
				}
				ms.Close();
			}
			aes.Clear();
			return input;
		}

		/// <summary>
		/// Aes Decode
		/// </summary>
		/// <param name="input">input</param>
		/// <param name="key">key</param>
		/// <param name="iv">iv</param>
		/// <returns>return</returns>
		[Description("AES 对称解密")]
		public static byte[] AesDecode([Description("要解密的数据")]byte[] input, [Description("解密密钥")]byte[] key, [Description("解密向量")]byte[] iv)
		{
			if (input == null || input.Length == 0)
				return null;

			if ((key == null || key.Length == 0) &&
				(iv == null || iv.Length == 0))
				return null;

			var aes = RijndaelManaged.Create();
			if (key == null || key.Length == 0)
			{
				key = iv;
				if (iv.Length >= aes.KeySize + aes.KeySize / 2)
				{
					var vs = new byte[aes.KeySize];
					Array.Copy(iv, 0, vs, 0, vs.Length);
					aes.Key = vs;
					vs = new byte[aes.KeySize / 2];
					Array.Copy(iv, aes.KeySize, vs, 0, vs.Length);
					aes.IV = vs;
				}
				else
				{
					aes.Key = FillKey(key, aes.KeySize);
					aes.IV = FillKey(iv, aes.KeySize / 2);
				}
			}
			else if (iv == null || iv.Length == 0)
			{
				iv = key;
				if (key.Length >= aes.KeySize + aes.KeySize / 2)
				{
					var vs = new byte[aes.KeySize];
					Array.Copy(key, 0, vs, 0, vs.Length);
					aes.Key = vs;
					vs = new byte[aes.KeySize / 2];
					Array.Copy(key, aes.KeySize, vs, 0, vs.Length);
					aes.IV = vs;
				}
				else
				{
					aes.Key = FillKey(key, aes.KeySize);
					aes.IV = FillKey(iv, aes.KeySize / 2);
				}
			}
			else
			{
				aes.Key = FillKey(key, aes.KeySize);
				aes.IV = FillKey(iv, aes.KeySize / 2);
			}
			using (var ms = new MemoryStream(input))
			{
				using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
				{
					using (var rs = new MemoryStream())
					{
						while (true)
						{
							var i = cs.Read(input, 0, input.Length);
							if (i == 0)
								break;

							rs.Write(input, 0, i);
						}
						input = rs.ToArray();
						rs.Close();
					}
					cs.Close();
				}
				ms.Close();
			}
			aes.Clear();
			return input;
		}

		/// <summary>
		/// Des Encode
		/// </summary>
		/// <param name="input">input</param>
		/// <param name="key">key</param>
		/// <param name="iv">iv</param>
		/// <returns>return</returns>
		[Description("DES 对称加密")]
		public static byte[] DesEncode([Description("要加密的数据")]byte[] input, [Description("加密密钥")]byte[] key, [Description("加密向量")]byte[] iv)
		{
			if (input == null || input.Length == 0)
				return null;

			if ((key == null || key.Length == 0) &&
				(iv == null || iv.Length == 0))
				return null;

			var des = new DESCryptoServiceProvider();
			if (key == null || key.Length == 0)
			{
				key = iv;
				if (iv.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { iv[0x0], iv[0x2], iv[0x4], iv[0x6], iv[0x8], iv[0xA], iv[0xC], iv[0xE] };
					des.IV = new byte[] { iv[0x1], iv[0x3], iv[0x5], iv[0x7], iv[0x9], iv[0xB], iv[0xD], iv[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else if (iv == null || iv.Length == 0)
			{
				iv = key;
				if (key.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { key[0x0], key[0x2], key[0x4], key[0x6], key[0x8], key[0xA], key[0xC], key[0xE] };
					des.IV = new byte[] { key[0x1], key[0x3], key[0x5], key[0x7], key[0x9], key[0xB], key[0xD], key[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else
			{
				des.Key = FillKey(key, des.KeySize);
				des.IV = FillKey(iv, des.KeySize);
			}
			using (var ms = new MemoryStream())
			{
				using (var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
				{
					cs.Write(input, 0, input.Length);
					cs.FlushFinalBlock();
					cs.Close();
					input = ms.ToArray();
				}
				ms.Close();
			}
			des.Clear();
			return input;
		}

		/// <summary>
		/// Des Decode
		/// </summary>
		/// <param name="input">input</param>
		/// <param name="key">key</param>
		/// <param name="iv">iv</param>
		/// <returns>return</returns>
		[Description("DES 对称解密")]
		public static byte[] DesDecode([Description("要解密的数据")]byte[] input, [Description("解密密钥")]byte[] key, [Description("解密向量")]byte[] iv)
		{
			if (input == null || input.Length == 0)
				return null;

			if ((key == null || key.Length == 0) &&
				(iv == null || iv.Length == 0))
				return null;

			var des = new DESCryptoServiceProvider();
			if (key == null || key.Length == 0)
			{
				key = iv;
				if (iv.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { iv[0x0], iv[0x2], iv[0x4], iv[0x6], iv[0x8], iv[0xA], iv[0xC], iv[0xE] };
					des.IV = new byte[] { iv[0x1], iv[0x3], iv[0x5], iv[0x7], iv[0x9], iv[0xB], iv[0xD], iv[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else if (iv == null || iv.Length == 0)
			{
				iv = key;
				if (key.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { key[0x0], key[0x2], key[0x4], key[0x6], key[0x8], key[0xA], key[0xC], key[0xE] };
					des.IV = new byte[] { key[0x1], key[0x3], key[0x5], key[0x7], key[0x9], key[0xB], key[0xD], key[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else
			{
				des.Key = FillKey(key, des.KeySize);
				des.IV = FillKey(iv, des.KeySize);
			}
			using (var ms = new MemoryStream(input))
			{
				using (var cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
				{
					using (var rs = new MemoryStream())
					{
						while (true)
						{
							var i = cs.Read(input, 0, input.Length);
							if (i == 0)
								break;

							rs.Write(input, 0, i);
						}
						input = rs.ToArray();
						rs.Close();
					}
					cs.Close();
				}
				ms.Close();
			}
			des.Clear();
			return input;
		}

		/// <summary>
		/// Tdes Encode
		/// </summary>
		/// <param name="input">input</param>
		/// <param name="key">key</param>
		/// <param name="iv">iv</param>
		/// <returns>return</returns>
		[Description("TDES 对称加密")]
		public static byte[] TdesEncode([Description("要加密的数据")]byte[] input, [Description("加密密钥")]byte[] key, [Description("加密向量")]byte[] iv)
		{
			if (input == null || input.Length == 0)
				return null;

			if ((key == null || key.Length == 0) &&
				(iv == null || iv.Length == 0))
				return null;

			var des = new DESCryptoServiceProvider();
			if (key == null || key.Length == 0)
			{
				key = iv;
				if (iv.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { iv[0x0], iv[0x2], iv[0x4], iv[0x6], iv[0x8], iv[0xA], iv[0xC], iv[0xE] };
					des.IV = new byte[] { iv[0x1], iv[0x3], iv[0x5], iv[0x7], iv[0x9], iv[0xB], iv[0xD], iv[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else if (iv == null || iv.Length == 0)
			{
				iv = key;
				if (key.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { key[0x0], key[0x2], key[0x4], key[0x6], key[0x8], key[0xA], key[0xC], key[0xE] };
					des.IV = new byte[] { key[0x1], key[0x3], key[0x5], key[0x7], key[0x9], key[0xB], key[0xD], key[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else
			{
				des.Key = FillKey(key, des.KeySize);
				des.IV = FillKey(iv, des.KeySize);
			}
			using (var ms = new MemoryStream())
			{
				using (var cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
				{
					cs.Write(input, 0, input.Length);
					cs.FlushFinalBlock();
					cs.Close();
					input = ms.ToArray();
				}
				ms.Close();
			}
			des.Clear();
			return input;
		}

		/// <summary>
		/// Tdes Decode
		/// </summary>
		/// <param name="input">input</param>
		/// <param name="key">key</param>
		/// <param name="iv">iv</param>
		/// <returns>return</returns>
		[Description("TDES 对称解密")]
		public static byte[] TdesDecode([Description("要解密的数据")]byte[] input, [Description("解密密钥")]byte[] key, [Description("解密向量")]byte[] iv)
		{
			if (input == null || input.Length == 0)
				return null;

			if ((key == null || key.Length == 0) &&
				(iv == null || iv.Length == 0))
				return null;

			var des = new DESCryptoServiceProvider();
			if (key == null || key.Length == 0)
			{
				key = iv;
				if (iv.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { iv[0x0], iv[0x2], iv[0x4], iv[0x6], iv[0x8], iv[0xA], iv[0xC], iv[0xE] };
					des.IV = new byte[] { iv[0x1], iv[0x3], iv[0x5], iv[0x7], iv[0x9], iv[0xB], iv[0xD], iv[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else if (iv == null || iv.Length == 0)
			{
				iv = key;
				if (key.Length >= des.KeySize * 2)
				{
					des.Key = new byte[] { key[0x0], key[0x2], key[0x4], key[0x6], key[0x8], key[0xA], key[0xC], key[0xE] };
					des.IV = new byte[] { key[0x1], key[0x3], key[0x5], key[0x7], key[0x9], key[0xB], key[0xD], key[0xF] };
				}
				else
				{
					des.Key = FillKey(key, des.KeySize);
					des.IV = FillKey(iv, des.KeySize);
				}
			}
			else
			{
				des.Key = FillKey(key, des.KeySize);
				des.IV = FillKey(iv, des.KeySize);
			}
			using (var ms = new MemoryStream(input))
			{
				using (var cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
				{
					using (var rs = new MemoryStream())
					{
						while (true)
						{
							var i = cs.Read(input, 0, input.Length);
							if (i == 0)
								break;

							rs.Write(input, 0, i);
						}
						input = rs.ToArray();
						rs.Close();
					}
					cs.Close();
				}
				ms.Close();
			}
			des.Clear();
			return input;
		}

		/// <summary>
		/// Md5 Crypto
		/// </summary>
		/// <param name="data">data</param>
		/// <returns>MD5</returns>
		[Description("MD5 单向哈希加密")]
		public static byte[] Md5Crypto([Description("要加密的数据")]byte[] data)
		{
			if (data == null)
				data = Reflector.Generic<byte>.EmptyArray;

			using (var md5 = MD5.Create())
				data = md5.ComputeHash(data);
			return data;
		}

		/// <summary>
		/// Sha1 Crypto
		/// </summary>
		/// <param name="data">data</param>
		/// <returns>Sha1</returns>
		[Description("SHA1 单向哈希加密")]
		public static byte[] Sha1Crypto([Description("要加密的数据")]byte[] data)
		{
			if (data == null)
				data = Reflector.Generic<byte>.EmptyArray;

			using (var sha = SHA1.Create())
				data = sha.ComputeHash(data);
			return data;
		}

		/// <summary>
		/// Sha256 Crypto
		/// </summary>
		/// <param name="data">data</param>
		/// <returns>Sha256</returns>
		[Description("SHA256 单向哈希加密")]
		public static byte[] Sha256Crypto([Description("要加密的数据")]byte[] data)
		{
			if (data == null)
				data = Reflector.Generic<byte>.EmptyArray;

			using (var sha = SHA256.Create())
				data = sha.ComputeHash(data);
			return data;
		}

		/// <summary>
		/// Sha384 Crypto
		/// </summary>
		/// <param name="data">data</param>
		/// <returns>Sha384</returns>
		[Description("SHA384 单向哈希加密")]
		public static byte[] Sha384Crypto([Description("要加密的数据")]byte[] data)
		{
			if (data == null)
				data = Reflector.Generic<byte>.EmptyArray;

			using (var sha = SHA384.Create())
				data = sha.ComputeHash(data);
			return data;
		}

		/// <summary>
		/// Sha512 Crypto
		/// </summary>
		/// <param name="data">data</param>
		/// <returns>Sha512</returns>
		[Description("SHA512 单向哈希加密")]
		public static byte[] Sha512Crypto([Description("要加密的数据")]byte[] data)
		{
			if (data == null)
				data = Reflector.Generic<byte>.EmptyArray;

			using (var sha = SHA512.Create())
				data = sha.ComputeHash(data);
			return data;
		}

		private static byte[] Crypto(RSACryptoServiceProvider rsa, byte[] data, int buffer, bool isCrypto)
		{
			var l = data.Length;
			if (buffer <= 0)
			{
				buffer = rsa.KeySize / 8;
				if (isCrypto)
					buffer -= 11;
			}
			if (l > buffer)
			{
				using (var ms = new MemoryStream())
				{
					for (var i = 0; i < l; i += buffer)
					{
						var rs = new byte[l - i - buffer > 0 ? buffer : l - i];
						Array.Copy(data, i, rs, 0, rs.Length);
						if (isCrypto)
							rs = rsa.Encrypt(rs, false);
						else
							rs = rsa.Decrypt(rs, false);
						ms.Write(rs, 0, rs.Length);
					}
					data = ms.ToArray();
					ms.Close();
				}
				return data;
			}
			if (isCrypto)
				data = rsa.Encrypt(data, false);
			else
				data = rsa.Decrypt(data, false);
			return data;
		}

		/// <summary>
		/// 公钥 RSA 加密
		/// </summary>
		/// <param name="data">要加密的数据</param>
		/// <returns>已加密的数据</returns>
		[Description("RSA 不对称加密，公钥加密，私钥解密")]
		public static byte[] RsaEncrypt([Description("要加密的数据")]byte[] data)
		{
			return RsaEncrypt(data, Reflector.Generic<byte>.EmptyArray, 0);
		}

		/// <summary>
		/// 公钥 RSA 加密
		/// </summary>
		/// <param name="data">要加密的数据</param>
		/// <param name="buffer">分段加密的数据长度，为将来保留</param>
		/// <returns>已加密的数据</returns>
		[Description("RSA 不对称加密，公钥加密，私钥解密")]
		public static byte[] RsaEncrypt([Description("要加密的数据")]byte[] data, [Description("分段加密长度，可为空")]int buffer)
		{
			return RsaEncrypt(data, Reflector.Generic<byte>.EmptyArray, buffer);
		}

		/// <summary>
		/// 公钥 RSA 加密
		/// </summary>
		/// <param name="data">要加密的数据</param>
		/// <param name="key">公钥</param>
		/// <param name="buffer">分段加密的数据长度，为将来保留</param>
		/// <returns>已加密的数据</returns>
		[Description("RSA 不对称加密，公钥加密，私钥解密")]
		public static byte[] RsaEncrypt([Description("要加密的数据")]byte[] data, [Description("加密公钥")]byte[] key, [Description("分段加密长度")]int buffer)
		{
			if (data == null)
				return data;

			if (key == null)
				return data;

			if (data == null || data.Length == 0)
				return data;

			if (key == null)
				return data;

			if (key.Length == 0)
			{
				var cer = X509;
				var rsa = cer.PublicKey.Key as RSACryptoServiceProvider;
				if (rsa != null)
					data = Crypto(rsa, data, 0, true);
				return data;
			}

			using (var rsa = new RSACryptoServiceProvider())
			{
				rsa.ImportCspBlob(key);
				data = Crypto(rsa, data, 0, true);
			}
			return data;
		}

		/// <summary>
		/// 私钥 RSA 解密
		/// </summary>
		/// <param name="data">要解密的数据</param>
		/// <returns>已解密的数据</returns>
		[Description("RSA 不对称解密，公钥加密，私钥解密")]
		public static byte[] RsaDecrypt([Description("要解密的数据")]byte[] data)
		{
			return RsaDecrypt(data, Reflector.Generic<byte>.EmptyArray, 0);
		}

		/// <summary>
		/// 私钥 RSA 解密
		/// </summary>
		/// <param name="data">要解密的数据</param>
		/// <param name="buffer">分段加密的数据长度，为将来保留</param>
		/// <returns>已解密的数据</returns>
		[Description("RSA 不对称解密，公钥加密，私钥解密")]
		public static byte[] RsaDecrypt([Description("要解密的数据")]byte[] data, [Description("分段解密长度")]int buffer)
		{
			return RsaDecrypt(data, Reflector.Generic<byte>.EmptyArray, buffer);
		}

		/// <summary>
		/// 私钥 RSA 解密
		/// </summary>
		/// <param name="data">要解密的数据</param>
		/// <param name="key">私钥</param>
		/// <param name="buffer">分段加密的数据长度，为将来保留</param>
		/// <returns>已解密的数据</returns>
		[Description("RSA 不对称解密，公钥加密，私钥解密")]
		public static byte[] RsaDecrypt([Description("要解密的数据")]byte[] data, [Description("解密私钥")]byte[] key, [Description("分段解密长度")]int buffer)
		{
			if (data == null)
				return data;

			if (key == null)
				return data;

			if (data == null || data.Length == 0)
				return data;

			if (key == null)
				return data;

			if (key.Length == 0)
			{
				var cer = X509;
				var rsa = cer.PrivateKey as RSACryptoServiceProvider;
				if (rsa != null)
					data = Crypto(rsa, data, buffer, false);
				return data;
			}


			using (var rsa = new RSACryptoServiceProvider())
			{
				rsa.ImportCspBlob(key);
				data = Crypto(rsa, data, buffer, false);
			}
			return data;
		}

		/// <summary>
		/// RSA 加解密及获取公私钥。
		/// </summary>
		/// <param name="data">要加解密的数据</param>
		/// <param name="key">非空为加密</param>
		/// <param name="secret">非空为解密</param>
		/// <param name="buffer">分段加密的数据长度，为将来保留</param>
		/// <returns>操作结果</returns>
		[Description("RSA 不对称加解密，公钥加密，私钥解密")]
		[return: Description("返回零表示取公私密钥对，正数表示加密，负数表示解密")]
		public static int RsaCrypto([Description("要加解密的数据，空表示生成公私密钥对")]ref byte[] data, [Description("加密公钥，空表示解密")]ref byte[] key, [Description("解密私钥，空表示加密")]ref byte[] secret, [Description("分段加解密长度，可为空")]int buffer)
		{
			var rsa = new RSACryptoServiceProvider();
			if (data == null)
			{
				if (key == null)
					key = rsa.ExportCspBlob(false);
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				rsa.Clear();
				return 0;
			}

			if (data == null || data.Length == 0)
			{
				if (key == null)
					key = rsa.ExportCspBlob(false);
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				rsa.Clear();
				return 0;
			}

			if (key == null)
			{
				if (secret == null)//加密
				{
					key = rsa.ExportCspBlob(false);
					secret = rsa.ExportCspBlob(true);
					data = Crypto(rsa, data, buffer, true);//加密
					rsa.Clear();
					return 1;
				}

				rsa.ImportCspBlob(secret);
				key = rsa.ExportCspBlob(false);
				//iv = rsa.ToXmlString(true);
				data = Crypto(rsa, data, buffer, false);//解密
				rsa.Clear();
				return -1;
			}

			rsa.ImportCspBlob(key);
			data = Crypto(rsa, data, buffer, true);//加密
			rsa.Clear();
			return 2;
		}

		/// <summary/>
		[Description("RSA 不对称签名，私钥签名，公钥验证")]
		public static byte[] RsaSignData([Description("要签名的数据")]byte[] data)
		{
			if (data == null)
				return data;

			return RsaSignData(data, Reflector.Generic<byte>.EmptyArray, null, 0, data.Length);
		}

		/// <summary/>
		[Description("RSA 不对称签名，私钥签名，公钥验证")]
		public static byte[] RsaSignData([Description("要签名的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid)
		{
			if (data == null)
				return data;

			return RsaSignData(data, Reflector.Generic<byte>.EmptyArray, oid, 0, data.Length);
		}

		/// <summary/>
		[Description("RSA 不对称签名，私钥签名，公钥验证")]
		public static byte[] RsaSignData([Description("要签名的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid, [Description("签名起始位置")]int offset, [Description("签名结束位置")]int count)
		{
			return RsaSignData(data, Reflector.Generic<byte>.EmptyArray, oid, offset, count);
		}

		/// <summary/>
		[Description("RSA 不对称签名，私钥签名，公钥验证")]
		public static byte[] RsaSignData([Description("要签名的数据")]byte[] data, [Description("签名私钥")]byte[] key, [Description("签名哈希算法，可为空")]string oid, [Description("签名起始位置")]int offset, [Description("签名结束位置，可为空")]int count)
		{
			if (data == null)
				return data;

			if (key == null)
				return data;

			if (data == null || data.Length == 0)
				return data;

			if (key == null)
				return data;

			if (key.Length == 0)
			{
				data = (X509.PrivateKey as RSACryptoServiceProvider).SignData(data, offset, count, new SHA1CryptoServiceProvider());
				return data;
			}

			var rsa = new RSACryptoServiceProvider();
			rsa.ImportCspBlob(key);
			data = rsa.SignData(data, offset, count, string.IsNullOrEmpty(oid) ? new SHA1CryptoServiceProvider() : HashAlgorithm.Create(oid));
			return data;
		}

		/// <summary/>
		[Description("RSA 不对称哈希签名，私钥签名，公钥验证")]
		public static byte[] RsaSignHash([Description("要签名的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid)
		{
			return RsaSignHash(data, Reflector.Generic<byte>.EmptyArray, oid);
		}

		/// <summary/>
		[Description("RSA 不对称哈希签名，私钥签名，公钥验证")]
		public static byte[] RsaSignHash([Description("要签名的数据")]byte[] data, [Description("签名私钥")]byte[] key, [Description("签名哈希算法，可为空")]string oid)
		{
			if (data == null)
				return data;

			if (key == null)
				return data;

			if (data == null || data.Length == 0)
				return data;

			if (key == null)
				return data;

			if (key.Length == 0)
			{
				data = (X509.PrivateKey as RSACryptoServiceProvider).SignHash(data, (string.IsNullOrEmpty(oid)) ? X509.SignatureAlgorithm.Value : CryptoConfig.MapNameToOID(oid));
				return data;
			}

			var rsa = new RSACryptoServiceProvider();
			rsa.ImportCspBlob(key);
			data = rsa.SignHash(data, (string.IsNullOrEmpty(oid)) ? null : CryptoConfig.MapNameToOID(oid));
			return data;
		}

		/// <summary/>
		[Description("RSA 不对称验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] RsaVerifyData([Description("要验证的数据")]byte[] data, [Description("签名数据")]byte[] signature)
		{
			if (data == null)
				return data;

			return RsaVerifyData(data, Reflector.Generic<byte>.EmptyArray, null, 0, data.Length, signature);
		}

		/// <summary/>
		[Description("RSA 不对称验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] RsaVerifyData([Description("要验证的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid, [Description("签名数据")]byte[] signature)
		{
			if (data == null)
				return data;

			return RsaVerifyData(data, Reflector.Generic<byte>.EmptyArray, oid, 0, data.Length, signature);
		}

		/// <summary/>
		[Description("RSA 不对称验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] RsaVerifyData([Description("要验证的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid, [Description("签名起始位置")]int offset, [Description("签名结束位置")]int count, [Description("签名数据")]byte[] signature)
		{
			return RsaVerifyData(data, Reflector.Generic<byte>.EmptyArray, oid, offset, count, signature);
		}

		/// <summary/>
		[Description("RSA 不对称验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] RsaVerifyData([Description("要验证的数据")]byte[] data, [Description("签名公钥")]byte[] key, [Description("签名哈希算法，可为空")]string oid, [Description("签名起始位置")]int offset, [Description("签名结束位置")]int count, [Description("签名数据")]byte[] signature)
		{
			if (data == null)
				return null;

			if (key == null)
				return null;

			if (data == null || data.Length == 0)
				return null;

			if (signature == null || signature.Length == 0)
				return null;

			if (key == null)
				return null;

			if (key.Length == 0)
			{
				if ((X509.PrivateKey as RSACryptoServiceProvider).VerifyData(data, string.IsNullOrEmpty(oid) ? new SHA1CryptoServiceProvider() : HashAlgorithm.Create(oid), signature))
					return data;

				return null;
			}

			var rsa = new RSACryptoServiceProvider();
			rsa.ImportCspBlob(key);
			if (data.Length > count)
			{
				var vs = new byte[count];
				Array.Copy(data, offset, vs, 0, count);
				data = vs;
			}
			if (rsa.VerifyData(data, new SHA1CryptoServiceProvider(), signature))
				return data;

			return null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="key"></param>
		/// <param name="oid"></param>
		/// <param name="signature"></param>
		/// <returns></returns>
		[Description("RSA 不对称哈希验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] RsaVerifyHash([Description("要验证的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid, [Description("签名数据")]byte[] signature)
		{
			return RsaVerifyHash(data, Reflector.Generic<byte>.EmptyArray, oid, signature);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="key"></param>
		/// <param name="oid"></param>
		/// <param name="signature"></param>
		/// <returns></returns>
		[Description("RSA 不对称哈希验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] RsaVerifyHash([Description("要验证的数据")]byte[] data, [Description("签名公钥")]byte[] key, [Description("签名哈希算法，可为空")]string oid, [Description("签名数据")]byte[] signature)
		{
			if (data == null)
				return null;

			if (key == null)
				return null;

			if (data == null || data.Length == 0)
				return null;

			if (signature == null || signature.Length == 0)
				return null;

			if (key == null)
				return null;

			if (key.Length == 0)
			{
				if ((X509.PrivateKey as RSACryptoServiceProvider).VerifyHash(data, string.IsNullOrEmpty(oid) ? X509.SignatureAlgorithm.Value : CryptoConfig.MapNameToOID(oid), signature))
					return data;

				return null;
			}

			var rsa = new RSACryptoServiceProvider();
			rsa.ImportCspBlob(key);
			if (rsa.VerifyHash(data, string.IsNullOrEmpty(oid) ? null : CryptoConfig.MapNameToOID(oid), signature))
				return data;

			return null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="offset"></param>
		/// <param name="count"></param>
		/// <param name="signature"></param>
		/// <param name="key"></param>
		/// <param name="secret"></param>
		/// <returns></returns>
		[Description("RSA 不对称签名与验证，私钥签名，公钥验证")]
		[return: Description("返回零表示取公私密钥对或验证成功，正数表示签名，负数表示验证失败")]
		public static int RsaSign([Description("要签名或验证的数据")]byte[] data, [Description("签名起始位置")]int offset, [Description("签名结束位置")]int count, [Description("签名数据")]ref byte[] signature, [Description("签名私钥，为空表示验证")]ref byte[] key, [Description("验证公钥，为空表示签名")]ref byte[] secret)
		{
			var rsa = new RSACryptoServiceProvider();
			if (data == null)
			{
				if (key == null)
					key = rsa.ExportCspBlob(false);
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				return 0;
			}

			if (data == null || data.Length == 0)
			{
				if (key == null)
					key = rsa.ExportCspBlob(false);
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				return 0;
			}


			if (signature ==null || (key == null && secret == null))//加密
			{
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				else
					rsa.ImportCspBlob(secret);
				if (key == null)
					key = rsa.ExportCspBlob(false);
				data = rsa.SignData(data, offset, count, new SHA1CryptoServiceProvider());//加密
				signature = data;
				return 1;
			}

			if (secret == null)
				rsa.ImportCspBlob(key);
			else
				rsa.ImportCspBlob(secret);
			if (key == null)
				key = rsa.ExportCspBlob(false);
			if (data.Length > count)
			{
				var vs = new byte[count];
				Array.Copy(data, offset, vs, 0, count);
				data = vs;
			}
			if (rsa.VerifyData(data, new SHA1CryptoServiceProvider(), signature))//解密
				return 0;

			signature = null;
			return -1;
		}

		/// <summary>
		/// DSA 加解密及获取公私钥。
		/// </summary>
		/// <param name="data"></param>
		/// <param name="oid"></param>
		/// <param name="signature"></param>
		/// <param name="key"></param>
		/// <param name="secret"></param>
		/// <returns></returns>
		[Description("RSA 不对称哈希签名与验证，私钥签名，公钥验证")]
		[return: Description("返回零表示取公私密钥对或验证成功，正数表示签名，负数表示验证失败")]
		public static int RsaHash([Description("要签名或验证的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid, [Description("签名数据")]ref byte[] signature, [Description("签名私钥，为空表示验证")]ref byte[] key, [Description("验证公钥，为空表示签名")]ref byte[] secret)
		{
			var rsa = new RSACryptoServiceProvider();
			if (data == null)
			{
				if (key == null)
					key = rsa.ExportCspBlob(false);
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				return 0;
			}

			if (data == null || data.Length == 0)
			{
				if (key == null)
					key = rsa.ExportCspBlob(false);
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				return 0;
			}

			if (signature == null || (key == null && secret == null))//加密
			{
				if (secret == null)
					secret = rsa.ExportCspBlob(true);
				else
					rsa.ImportCspBlob(secret);
				if (key == null)
					key = rsa.ExportCspBlob(false);
				data = rsa.SignHash(data, (oid == null || string.IsNullOrEmpty(oid)) ? null : CryptoConfig.MapNameToOID(oid));//加密
				signature = data;
				return 1;
			}

			if (secret == null)
				rsa.ImportCspBlob(key);
			else
				rsa.ImportCspBlob(secret);
			if (key == null)
				key = rsa.ExportCspBlob(false);
			if (rsa.VerifyHash(data, (oid == null || string.IsNullOrEmpty(oid)) ? null : CryptoConfig.MapNameToOID(oid), signature))//解密
				return 0;

			return -1;
		}

		#region DSA

		/// <summary/>
		[Description("DSA 不对称签名，私钥签名，公钥验证")]
		public static byte[] DsaSignData([Description("要签名的数据")]byte[] data, [Description("签名私钥")]byte[] key)
		{
			if (data == null)
				return data;

			return DsaSignData(data, key, 0, data.Length);
		}

		/// <summary/>
		[Description("DSA 不对称签名，私钥签名，公钥验证")]
		public static byte[] DsaSignData([Description("要签名的数据")]byte[] data, [Description("签名私钥")]byte[] key, [Description("签名起始位置")]int offset, [Description("签名结束位置")]int count)
		{
			if (data == null)
				return data;

			if (key == null)
				return data;

			if (data == null || data.Length == 0)
				return data;

			if (key == null || key.Length == 0)
				return data;

			var dsa = new DSACryptoServiceProvider();
			dsa.ImportCspBlob(key);
			data = dsa.SignData(data, offset, count);
			return data;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="key"></param>
		/// <param name="oid"></param>
		/// <returns></returns>
		[Description("DSA 不对称哈希签名，私钥签名，公钥验证")]
		public static byte[] DsaSignHash([Description("要签名的数据")]byte[] data, [Description("签名私钥")]byte[] key, [Description("签名哈希算法，可为空")]string oid)
		{
			if (data == null)
				return data;

			if (key == null)
				return data;

			if (data == null || data.Length == 0)
				return data;

			if (key == null || key.Length == 0)
				return data;

			var rsa = new DSACryptoServiceProvider();
			rsa.ImportCspBlob(key);
			data = rsa.SignHash(data, (string.IsNullOrEmpty(oid)) ? null : CryptoConfig.MapNameToOID(oid));
			return data;
		}

		/// <summary/>
		[Description("DSA 不对称验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] DsaVerifyData([Description("要验证的数据")]byte[] data, [Description("签名公钥")]byte[] key, [Description("签名数据")]byte[] signature)
		{
			if (data == null)
				return data;

			return DsaVerifyData(data, key, 0, data.Length, signature);
		}

		/// <summary/>
		[Description("DSA 不对称验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] DsaVerifyData([Description("要验证的数据")]byte[] data, [Description("签名公钥")]byte[] key, [Description("签名起始位置，可为空")]int offset, [Description("签名结束位置，可为空")]int count, [Description("签名数据")]byte[] signature)
		{
			if (data == null)
				return null;

			if (key == null)
				return null;

			if (data == null || data.Length == 0)
				return null;

			if (signature == null || signature.Length == 0)
				return null;

			if (key == null || key.Length == 0)
				return null;

			var rsa = new DSACryptoServiceProvider();
			rsa.ImportCspBlob(key);
			if (data.Length > count)
			{
				var vs = new byte[count];
				Array.Copy(data, offset, vs, 0, count);
				data = vs;
			}
			if (rsa.VerifyData(data, signature))
				return data;

			return null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="key"></param>
		/// <param name="oid"></param>
		/// <param name="signature"></param>
		/// <returns></returns>
		[Description("DSA 不对称哈希验证，私钥签名，公钥验证")]
		[return: Description("返回空表示验证失败，否则返回原输入的要验证数据")]
		public static byte[] DsaVerifyHash([Description("要验证的数据")]byte[] data, [Description("签名公钥")]byte[] key, [Description("签名哈希算法，可为空")]string oid, [Description("签名数据")]byte[] signature)
		{
			if (data == null)
				return null;

			if (key == null)
				return null;

			if (data == null || data.Length == 0)
				return null;

			if (signature == null || signature.Length == 0)
				return null;

			if (key == null || key.Length == 0)
				return null;

			var rsa = new DSACryptoServiceProvider();
			rsa.ImportCspBlob(key);
			if (rsa.VerifyHash(data, string.IsNullOrEmpty(oid) ? null : CryptoConfig.MapNameToOID(oid), signature))
				return data;

			return null;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="data"></param>
		/// <param name="offset"></param>
		/// <param name="count"></param>
		/// <param name="signature"></param>
		/// <param name="key"></param>
		/// <param name="secret"></param>
		/// <returns></returns>
		[Description("DSA 不对称签名与验证，私钥签名，公钥验证")]
		[return: Description("返回零表示取公私密钥对或验证成功，正数表示签名，负数表示验证失败")]
		public static int DsaSign([Description("要签名或验证的数据")]byte[] data, [Description("签名起始位置")]int offset, [Description("签名结束位置")]int count, [Description("签名数据")]ref byte[] signature, [Description("签名私钥，为空表示验证")]ref byte[] key, [Description("验证公钥，为空表示签名")]ref byte[] secret)
		{
			var dsa = new DSACryptoServiceProvider();
			if (data == null)
			{
				if (key == null)
					key = dsa.ExportCspBlob(false);
				if (secret == null)
					secret = dsa.ExportCspBlob(true);
				return 0;
			}

			if (data == null || data.Length == 0)
			{
				if (key == null)
					key = dsa.ExportCspBlob(false);
				if (secret == null)
					secret = dsa.ExportCspBlob(true);
				return 0;
			}


			if (signature ==null || (key == null && secret == null))//加密
			{
				if (secret == null)
					secret = dsa.ExportCspBlob(true);
				else
					dsa.ImportCspBlob(secret);
				if (key == null)
					key = dsa.ExportCspBlob(false);
				data = dsa.SignData(data, offset, count);//加密
				signature = data;
				return 1;
			}

			if (secret == null)
				dsa.ImportCspBlob(key);
			else
				dsa.ImportCspBlob(secret);
			if (key == null)
				key = dsa.ExportCspBlob(false);
			if (data.Length > count)
			{
				var vs = new byte[count];
				Array.Copy(data, offset, vs, 0, count);
				data = vs;
			}
			if (dsa.VerifyData(data, signature))//解密
				return 0;

			signature = null;
			return -1;
		}

		/// <summary>
		/// DSA 加解密及获取公私钥。
		/// </summary>
		/// <param name="data"></param>
		/// <param name="oid"></param>
		/// <param name="signature"></param>
		/// <param name="key"></param>
		/// <param name="secret"></param>
		/// <returns></returns>
		[Description("DSA 不对称哈希签名与验证，私钥签名，公钥验证")]
		[return: Description("返回零表示取公私密钥对或验证成功，正数表示签名，负数表示验证失败")]
		public static int DsaHash([Description("要签名或验证的数据")]byte[] data, [Description("签名哈希算法，可为空")]string oid, [Description("签名数据")]ref byte[] signature, [Description("签名私钥，为空表示验证")]ref byte[] key, [Description("验证公钥，为空表示签名")]ref byte[] secret)
		{
			var dsa = new DSACryptoServiceProvider();
			if (data == null)
			{
				if (key == null)
					key = dsa.ExportCspBlob(false);
				if (secret == null)
					secret = dsa.ExportCspBlob(true);
				return 0;
			}

			if (data == null || data.Length == 0)
			{
				if (key == null)
					key = dsa.ExportCspBlob(false);
				if (secret == null)
					secret = dsa.ExportCspBlob(true);
				return 0;
			}

			if (signature == null || (key == null && secret == null))//加密
			{
				if (secret == null)
					secret = dsa.ExportCspBlob(true);
				else
					dsa.ImportCspBlob(secret);
				if (key == null)
					key = dsa.ExportCspBlob(false);
				data = dsa.SignHash(data, (oid == null || string.IsNullOrEmpty(oid)) ? null : CryptoConfig.MapNameToOID(oid));//加密
				signature = data;
				return 1;
			}

			if (secret == null)
				dsa.ImportCspBlob(key);
			else
				dsa.ImportCspBlob(secret);
			if (key == null)
				key = dsa.ExportCspBlob(false);
			if (dsa.VerifyHash(data, (oid == null || string.IsNullOrEmpty(oid)) ? null : CryptoConfig.MapNameToOID(oid), signature))//解密
				return 0;

			return -1;
		}

		#endregion
	}
}
